Skip to content

Conversation

@tbaederr
Copy link
Contributor

When we see an array root, that pointer might yet again be an array element, so check for that.

When we see an array root, that pointer might yet again be an array
element, so check for that.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Oct 31, 2024
@llvmbot
Copy link
Member

llvmbot commented Oct 31, 2024

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

When we see an array root, that pointer might yet again be an array element, so check for that.


Full diff: https://github.com/llvm/llvm-project/pull/114400.diff

3 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Descriptor.cpp (+9-1)
  • (modified) clang/lib/AST/ByteCode/Pointer.cpp (+17-7)
  • (modified) clang/unittests/AST/ByteCode/toAPValue.cpp (+19-1)
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 5a8a2b64d5582d..39a54e4902cd2a 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -411,8 +411,16 @@ QualType Descriptor::getElemQualType() const {
   QualType T = getType();
   if (T->isPointerOrReferenceType())
     return T->getPointeeType();
-  if (const auto *AT = T->getAsArrayTypeUnsafe())
+  if (const auto *AT = T->getAsArrayTypeUnsafe()) {
+    // For primitive arrays, we don't save a QualType at all,
+    // just a PrimType. Try to figure out the QualType here.
+    if (isPrimitiveArray()) {
+      while (T->isArrayType())
+        T = T->getAsArrayTypeUnsafe()->getElementType();
+      return T;
+    }
     return AT->getElementType();
+  }
   if (const auto *CT = T->getAs<ComplexType>())
     return CT->getElementType();
   if (const auto *CT = T->getAs<VectorType>())
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index c9de039c195d94..54484853fcdaea 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -200,15 +200,26 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
   // Build the path into the object.
   Pointer Ptr = *this;
   while (Ptr.isField() || Ptr.isArrayElement()) {
+
     if (Ptr.isArrayRoot()) {
-      Path.push_back(APValue::LValuePathEntry(
-          {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
+      // An array root may still be an array element itself.
+      if (Ptr.isArrayElement()) {
+        Ptr = Ptr.expand();
+        unsigned Index = Ptr.getIndex();
+        Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
+        QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
+        Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
+        Ptr = Ptr.getArray();
+      } else {
+        Path.push_back(APValue::LValuePathEntry(
+            {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
 
-      if (const auto *FD =
-              dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
-        Offset += getFieldOffset(FD);
+        if (const auto *FD =
+                dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
+          Offset += getFieldOffset(FD);
 
-      Ptr = Ptr.getBase();
+        Ptr = Ptr.getBase();
+      }
     } else if (Ptr.isArrayElement()) {
       Ptr = Ptr.expand();
       unsigned Index;
@@ -219,7 +230,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
 
       QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
       Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
-
       Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
       Ptr = Ptr.getArray();
     } else {
diff --git a/clang/unittests/AST/ByteCode/toAPValue.cpp b/clang/unittests/AST/ByteCode/toAPValue.cpp
index 3f141878fb9594..cd62338ee23c14 100644
--- a/clang/unittests/AST/ByteCode/toAPValue.cpp
+++ b/clang/unittests/AST/ByteCode/toAPValue.cpp
@@ -22,7 +22,9 @@ TEST(ToAPValue, Pointers) {
       "constexpr S d = {{{true, false}, {false, true}, {false, false}}};\n"
       "constexpr const bool *b = &d.a[1].z;\n"
       "const void *p = (void*)12;\n"
-      "const void *nullp = (void*)0;\n";
+      "const void *nullp = (void*)0;\n"
+      "extern int earr[5][5];\n"
+      "constexpr const int *arrp = &earr[2][4];\n";
 
   auto AST = tooling::buildASTFromCodeWithArgs(
       Code, {"-fexperimental-new-constant-interpreter"});
@@ -87,6 +89,22 @@ TEST(ToAPValue, Pointers) {
     ASSERT_TRUE(Success);
     ASSERT_EQ(I, 0);
   }
+
+  // A multidimensional array.
+  {
+    const ValueDecl *D = getDecl("arrp");
+    ASSERT_NE(D, nullptr);
+    const Pointer &GP = getGlobalPtr("arrp").deref<Pointer>();
+    APValue A = GP.toAPValue(ASTCtx);
+    ASSERT_TRUE(A.isLValue());
+    ASSERT_TRUE(A.hasLValuePath());
+    ASSERT_EQ(A.getLValuePath().size(), 2u);
+    ASSERT_EQ(A.getLValuePath()[0].getAsArrayIndex(), 2u);
+    ASSERT_EQ(A.getLValuePath()[1].getAsArrayIndex(), 4u);
+    ASSERT_EQ(A.getLValueOffset().getQuantity(), 56u);
+    ASSERT_TRUE(
+        GP.atIndex(0).getFieldDesc()->getElemQualType()->isIntegerType());
+  }
 }
 
 TEST(ToAPValue, FunctionPointers) {

@tbaederr tbaederr merged commit 2c82079 into llvm:main Oct 31, 2024
11 checks passed
smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
llvm#114400)

When we see an array root, that pointer might yet again be an array
element, so check for that.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
llvm#114400)

When we see an array root, that pointer might yet again be an array
element, so check for that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants